package com.example.framework509.codeGen.service.impl;

import com.example.framework509.codeGen.entity.Entity;
import com.example.framework509.codeGen.entity.Field;
import com.example.framework509.codeGen.entity.Mapper;
import com.example.framework509.codeGen.entity.middlePojp.EntityContainer;
import com.example.framework509.codeGen.entity.middlePojp.EntityInfo;
import com.example.framework509.codeGen.entity.middlePojp.FieldContainer;
import com.example.framework509.codeGen.utils.AnnotationUtil;
import com.example.framework509.codeGen.utils.CodeGenUtils;
import com.example.framework509.common.exceptions.NotExistException;
import com.mysql.cj.util.StringUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipOutputStream;

@Service
public class CodeGenServiceImpl {

    @Autowired
    private EntityServiceImpl entityService;
    @Autowired
    private MapperServiceImpl mapperService;
    @Autowired
    private EntityFieldMapperServiceImpl entityFieldMapperService;
    @Autowired
    private CodeGenUtils codeGenUtils;
    @Autowired
    private AnnotationUtil annotationUtil;

    public List<EntityContainer> getEntitiesInfo() throws Exception {
        List<EntityInfo> entitiesInfo = new ArrayList<>();
        List<Entity> allEntities = entityService.getAllEntities();
        for (Entity entity : allEntities) {
            EntityInfo entityInfo = new EntityInfo();
            entityInfo.setId(entity.getId());
            entityInfo.setName(entity.getName());
            entityInfo.setModule(entity.getModule());
            entitiesInfo.add(entityInfo);
        }
        List<Mapper> allMappers = mapperService.getAllEntities();
        for (Mapper mapper : allMappers) {
            EntityInfo entityInfo = new EntityInfo();
            Entity primaryEntity = entityService.getEntityFromRedisProp("id", mapper.getPrimaryEntityId().toString());
            Entity secondaryEntity = entityService.getEntityFromRedisProp("id", mapper.getSecondaryEntityId().toString());
            entityInfo.setName(primaryEntity.getName() + secondaryEntity.getName() + "Mapper");
            entityInfo.setModule(primaryEntity.getModule());
            entityInfo.setMapperType(mapper.getMapperType());
            entityInfo.setPrimaryEntity(primaryEntity.getName());
            entityInfo.setPrimaryModule(primaryEntity.getModule());
            entityInfo.setSecondaryEntity(secondaryEntity.getName());
            entityInfo.setSecondaryModule(secondaryEntity.getModule());
            entitiesInfo.add(entityInfo);
        }
        List<EntityContainer> containers = new ArrayList<>();
        for (EntityInfo entityInfo : entitiesInfo) {
            //mapperEntity
            List<FieldContainer> fieldContainers = new ArrayList<>();
            if (!StringUtils.isNullOrEmpty(entityInfo.getMapperType())) {
                if (StringUtils.isNullOrEmpty(entityInfo.getPrimaryEntity()) || StringUtils.isNullOrEmpty(entityInfo.getSecondaryEntity()))
                    throw new NotExistException("MapperEntity Config has an empty Error");
                //添加关联表名称
                entityInfo.setPrimaryEntity(entityInfo.getPrimaryEntity());
                entityInfo.setPrimaryModule(entityInfo.getPrimaryModule());
                entityInfo.setSecondaryEntity(entityInfo.getSecondaryEntity());
                entityInfo.setSecondaryModule(entityInfo.getSecondaryModule());
            } else {
                //entity
                List<Field> fields = entityFieldMapperService.getSecondaryEntityFromPrimaryId(entityInfo.getId());
                for (Field field : fields) {
                    List<String> annotations = annotationUtil.convertAnnotation(field.getAnnotation(), false);
                    fieldContainers.add(new FieldContainer(field, annotations));
                }
            }
            EntityContainer container = new EntityContainer(entityInfo, fieldContainers);
            containers.add(container);
        }
        return containers;
    }

    public byte[] generatorCode(List<EntityContainer> entitiesInfo, String mainPath) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(outputStream);

        for (EntityContainer container : entitiesInfo) {
            codeGenUtils.build(container, mainPath, zip);
        }

        File folder = new File("src/main/resources/static");
        if (folder.exists()) {
            codeGenUtils.addStaticFile(mainPath, "src/main/resources/static", zip);
        }

        IOUtils.closeQuietly(zip);
        return outputStream.toByteArray();
    }

}
